home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UTIL / MEMORY / VIRTUASRC / !Virtual / c / control next >
Text File  |  1993-09-07  |  36KB  |  1,386 lines

  1. /*
  2.  * control.c
  3.  * Part of the !Virtual distribution
  4.  * (c) bdb/nas/fo, 1992-3
  5.  */
  6.  
  7. /* includes */
  8. #include "swis.h"
  9. #include "swiv.h"
  10. #include "wimp.h"
  11.  
  12. #include "virtual.h"
  13. #include "lib.h"
  14. #include "pager.h"
  15. #include "output.h"
  16. #include "asm.h"
  17. #include "poll.h"
  18.  
  19. #include "xswis.h"      /* Some RO3 swis */
  20.  
  21. /* constants */
  22. /*#define DEBUG*/
  23.  
  24. #define N_bit 0x80000000
  25. #define Z_bit 0x40000000
  26. #define C_bit 0x20000000
  27. #define V_bit 0x10000000
  28. #define PSW_bits 0xF0000000
  29.  
  30. static int * const swivec=(int*)8;
  31. static int wimp_version;
  32.  
  33. /* errors */
  34. #define ERR(x) ((struct Error *)(x))
  35. static char BadMemory[] = { "XXXXNo memory at this address" };
  36. static char Failed[] = { "XXXXMisc Virtual swi failed" };
  37. static char NotAllowed[] = { "XXXXThis swi not allowed under virtual" };
  38.  
  39. /* module wrapping */
  40.  struct Error *Cinit(private **p) /* */
  41. { /* called with C stack a 1K bit out of svcstack. */
  42.   struct Error *err;
  43.   if (!*p)
  44.     *p=alloc(sizeof(private));
  45.   (*p)->uses = 0;
  46.   (*p)->w = 0;
  47.   worksemaphore = 1;
  48.   err = swix(OS_CallEvery,IN(R0|R1|R2),15,&OurCallEvery,*p);
  49.   if (err)
  50.     free(*p),*p=0;
  51.   return err;
  52. }
  53.  
  54.  struct Error *Cfinish(private **p)
  55. { /* called with C stack a 1K bit out of svcstack. */
  56.   /* should check (*p)->uses */
  57.   return swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,*p);
  58. }
  59.  
  60.  struct Error *CDoPhysical(int task, int addr, int len, int k[3],private *priv) 
  61. { /* called with C stack a 1K bit out of svcstack. */
  62.   WKSP *w=priv->w;
  63.   RANGE r;
  64.   if (w->ourtask!=task)
  65.     return 0;
  66.   r = Locate(w,addr,addr+len);
  67.   k[0]=r.start; k[1]=r.end; k[2]=w->pagefile;  
  68.   return 0;
  69. }
  70.  
  71.  
  72. /* ******************** mode changers */
  73.  void ClaimVVecs(WKSP *w) 
  74. { int oldswi;
  75.   workptr=w;
  76.   swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),2,&VPrefetchAbort,&w->OldPrefetchAbort);
  77.   swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),3,&VDataAbort,&w->OldDataAbort);
  78.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),7,&VCallBack,w,&w->regs,
  79.                                    &w->OldCallBack,&w->OldCallBackR12,&w->OldCallBackRegs);
  80.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&VError,&w->errnum,&w->errPC);
  81.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&VUpCall,w);
  82.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&VExit,w);
  83.   oldswi=*swivec;
  84.   if (oldswi>>24==0xEA)
  85.     ; /* B */
  86.   oldswi=8+(int)swivec+(oldswi<<8>>6);
  87.   w->OldSWIV=oldswi;
  88.   workOldSWIV=oldswi;
  89.   *swivec=(int)&VSWIV-8-(int)swivec>>2|0xEA000000;
  90. }
  91.  
  92.  void ReleaseVVecs(WKSP *w) 
  93. {
  94.   *swivec=w->OldSWIV-8-(int)swivec>>2|0xEA000000;
  95.   swi(OS_ChangeEnvironment,IN(R0|R1),2,w->OldPrefetchAbort);
  96.   swi(OS_ChangeEnvironment,IN(R0|R1),3,w->OldDataAbort);
  97.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),7,w->OldCallBack,w->OldCallBackR12,w->OldCallBackRegs);
  98.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
  99.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
  100.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
  101. }
  102.  
  103.  void ClaimExtVecs( WKSP *w ) 
  104. { swi(OS_Claim,IN(R0|R1|R2),3,&ExtWriteC,w);
  105.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&ExtError,w,&w->errPC);
  106.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&ExtUpCall,w);
  107.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&ExtExit,w);
  108. }
  109.  
  110.  void ReleaseExtVecs( WKSP *w ) 
  111. { swi(OS_Release,IN(R0|R1|R2),3,&ExtWriteC,w);
  112.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
  113.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
  114.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
  115. }
  116.  
  117.  void Virtual(WKSP *w) 
  118. {
  119.   virtualmem(w);
  120.   ClaimVVecs(w);
  121. }
  122.  
  123.  void Normal(WKSP *w) 
  124. {
  125.   ReleaseVVecs(w);
  126.   normalmem(w);
  127. }
  128.  
  129.  void V2Ext( WKSP *w ) 
  130. {
  131.   ReleaseVVecs(w);
  132.   ClaimExtVecs(w);
  133. }
  134.  
  135.  void Ext2V( WKSP *w ) 
  136. {
  137.   ReleaseExtVecs(w);
  138.   ClaimVVecs(w);
  139. }
  140.  
  141.  void Ext2Norm( WKSP *w) 
  142. {
  143.   ReleaseExtVecs(w);
  144.   normalmem(w);
  145. }
  146.  
  147.  void Norm2Ext( WKSP *w) 
  148. {
  149.   virtualmem(w);
  150.   ClaimExtVecs(w);
  151. }
  152.  
  153.  
  154. /* ******************** Virtual mode handlers */
  155.  WKSP *CVWantAddr(WKSP *w, int start, int len) 
  156. {
  157.   if (len<0)
  158.     start += len, len= -len;
  159.   if (w->regs[15]&3)
  160.   { Normal(w);
  161.     printf("***** CWantAddr called from non-user mode. Disaster! *****\n");
  162.     RealDoOff(w);
  163.   }
  164.   if (!WriteRange(w,start,start+len))
  165.   { Normal(w);
  166.     printf("***** CWantAddr can't get desired area: %08x+%08x****\n",start,len);
  167.     RealDoOff(w);
  168.   }
  169.   return w;
  170. }
  171.  
  172.  void doeschand(WKSP *w,int n) 
  173. { w->EscapeCondition = n;
  174.   if (w->Escape != -1) {
  175.     int result, * ruser = w->regs;
  176.     if (w->EscapeR12 != -1)
  177.         WriteRange(w, w->EscapeR12, w->EscapeR12+512);
  178.     ReadRange(w, w->Escape, w->Escape+8);
  179.     result = CallEscapeHandler(w->Escape, w->EscapeR12, (w->EscapeCondition == 2) ? 0x40 : 0);
  180.     if (result == 1) {
  181.         int j, * rcallback = (int *) w->CallBackBuf;
  182.         /* call back flag is set */
  183.         WriteRange(w, w->CallBackR12, w->CallBackR12 + 512);
  184.         WriteRange(w, w->CallBackBuf, w->CallBackBuf + 16 * 4);
  185.         ReadRange(w, w->CallBack, w->CallBack + 8);
  186.         for (j = 0; j < 16; j++)
  187.                 rcallback[j] = ruser[j];        /* save user registers into callback buffer */
  188.         ruser[12] = w->CallBackR12;
  189.         ruser[15] = w->CallBack;
  190.     }
  191.   }
  192. }
  193.  
  194.  WKSP *CVCallBack(WKSP *w) 
  195. { Normal(w);
  196.   Poll(w);
  197.   Virtual(w);
  198.   if (1==w->EscapeCondition)
  199.     doeschand(w,2);
  200.   worksemaphore=1;      /* Ready to reenable when we exit */
  201.   return w;
  202. }
  203.  
  204.  WKSP *CVSWIV(WKSP *w,int instr) 
  205. {
  206.   int *r=w->regs;
  207.   char s[256];
  208.   struct Error *err=0;
  209.   int psw,i;
  210.   int swinum=instr&~(XOS_Bit|0xFF000000);
  211.   r[15]&=~V_bit;
  212. #if 0
  213.     Normal(w);
  214.     swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
  215.     printf("Swi %s PC=%08x ",s,r[15]);
  216.     for (i=0;i<=14;i++)
  217.       printf("R%d=%08x ",i,r[i]);
  218.     printf("...");
  219.     Virtual(w);
  220. #endif
  221.   switch(swinum) {
  222.   /* input/output */
  223.  
  224.    /*
  225.     * OS SWIs
  226.     */
  227.  
  228.    case OS_WriteC: 
  229.     outc(w,r[0]);
  230.     break;
  231.   
  232.    case OS_Write0: 
  233.     { char *p;
  234.       ReadRange(w,r[0],r[0]+1);
  235.       for (p=(char *)r[0];*p;p++)
  236.       { ReadPtr(w,(int)p);
  237.         outc(w,*p);
  238.       }
  239.       r[0]=(int)++p;
  240.     }
  241.     break;
  242.   
  243.    case OS_WriteS: 
  244.     { char *p=(char *)(r[15]&~0xfc000003);
  245.       char *q=p;
  246.       for (;*p;p++)
  247.       { ReadPtr(w,(int)p);
  248.         outc(w,*p);
  249.       }
  250.       r[15]+=(((p+1)-q)|3)+1;
  251.     }
  252.     break;
  253.   
  254.    case OS_WriteN: 
  255.     { int n;
  256.       for ( n=0; n<r[1]; n++ )
  257.       { ReadPtr(w,r[0]+n);
  258.         outc(w,((char *)r[0])[n]);
  259.       }
  260.     }
  261.     break;
  262.   
  263.    case OS_NewLine: 
  264.     outc(w,'\r'); outc(w,'\n');
  265.     break;
  266.   
  267.    case OS_ReadC: 
  268.     r[0]=getc(w);
  269.     if (-1==r[0])
  270.     { r[0] = 27;
  271.       r[15]|=C_bit;
  272.     }
  273.     else
  274.       r[15]&=~C_bit;
  275.     if (1==w->EscapeCondition)
  276.       doeschand(w,2);
  277.     break;
  278.   
  279.    case OS_ReadLine: 
  280.     { char buf[256];
  281.       int n=0,c;
  282.       r[15]&=~C_bit;
  283.       for (;;)
  284.       { c=getc(w);
  285.         switch (c)
  286.         {
  287.            case 13: case 10: 
  288.             buf[n]=13;
  289.             break;
  290.           
  291.            case 27: case -1: 
  292.             r[15]|=C_bit;
  293.             break;
  294.           
  295.            case 127: case 8: 
  296.             if (n>0)
  297.             { outc(w,127); n--; }
  298.             else
  299.               outc(w,7);
  300.             continue;
  301.           
  302.            case 21: 
  303.             while (n>0)
  304.             { outc(w,127); n--; }
  305.             continue;
  306.           
  307.            default: 
  308.             if (r[2]<=c && c<=r[3])
  309.             { if (n<r[1]-1 && n<255)
  310.               { buf[n++]=c;
  311.                 outc(w,c);
  312.               }
  313.               else
  314.                 outc(w,7);
  315.             }
  316.             else
  317.               outc(w,7);
  318.             continue;
  319.           
  320.         }
  321.         outc(w,'\r'); outc(w,'\n');
  322.         break;
  323.       }
  324.       WriteRange(w,r[0],r[0]+n+1);
  325.       memcpy((void *)r[0],buf,n+1);
  326.       r[1]=n;
  327.     }
  328.     if (1==w->EscapeCondition)
  329.       doeschand(w,2);
  330.     break;
  331.  
  332.    case OS_Byte: 
  333.     switch (r[0])
  334.     { default: goto uk;
  335.       case 0:           /* display os version */
  336.         Normal(w);
  337.         err = swix(OS_Byte,IN(R0|R1)|OUT(R1),0,r[1],&r[1]);
  338.         Virtual(w);
  339.         break;
  340.       case 2:           /* switch input streams */
  341. #ifdef DEBUG
  342.         Normal(w);
  343.         printf("(FX 2,%d)",r[1]);
  344.         Virtual(w);
  345. #endif
  346.         break;
  347.       case 3:           /* switch output streams */
  348. #ifdef DEBUG
  349.         Normal(w);
  350.         printf("(FX 3,%d)",r[1]);
  351.         Virtual(w);
  352. #endif
  353.         break;
  354.       case 15:          /* clear input or all buffers */
  355.         break;
  356.       case 21:          /* clear specific buffer */
  357.         break;
  358.       case 124:         /* clear esc cond immed */
  359.         w->EscapeCondition = 0;
  360.         break;
  361.       case 125:         /* cause esc cond */
  362.         doeschand(w,2);
  363.         break;
  364.       case 126:         /* acknowledge escape cond */
  365.         r[1]=w->EscapeCondition?0xff:0;
  366.         if (w->EscapeCondition)
  367.           doeschand(w,0);
  368.         break;
  369.       case 129:         /* read keyboard for information */
  370.         if (r[2] != 0xFF)
  371.         {
  372.           r[1]=lowgetc(w);
  373.           if (r[1] == -1) r[2] = 0xFF;
  374.             else r[2] = 0;
  375.         } else goto uk;
  376.         break;
  377.       case 160:
  378.       case 161:
  379.         err = swix(OS_Byte,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
  380.         break;
  381.       case 0xDA:        /* Read/write bytes in VDU queue */
  382.         r[1]=0;
  383.         break;
  384.       case 0xDC:        /* Read/write escape character */
  385.         { int old = w->EscapeChar;
  386.           w->EscapeChar = (w->EscapeChar&r[2])^r[1];
  387.           r[1] = old;
  388.           break;
  389.         }
  390.       case 0xE5:      /* Read/write escape char enable */
  391.         { int old = w->EscapeCharEnable;
  392.           w->EscapeCharEnable = (w->EscapeCharEnable&r[2])^r[1];
  393.           r[1] = old;
  394.           break;
  395.         }
  396.     }
  397.     break;
  398.  
  399.    case OS_Plot: 
  400.     Normal(w);
  401.     err = swix(OS_Plot,IN(R0|R1|R2),r[0],r[1],r[2]);
  402.     Virtual(w);
  403.     break;
  404.  
  405.    case OS_SerialOp: 
  406.     err = ERR(&NotAllowed);
  407.     break;
  408.   
  409.    case OS_Word: 
  410.     switch (r[0])
  411.     { default: goto uk;
  412.       case 1: case 2: case 3: case 4: case 14:
  413.         WriteRange(w, r[1],r[1]+256);
  414.         err = swix(OS_Word,IN(R0|R1),r[0],r[1]);
  415.         break;
  416.     }
  417.     break;
  418.   
  419.    case OS_ReadUnsigned: 
  420.     ReadRange(w,r[1],r[1]+256);
  421.     err = swix(OS_ReadUnsigned,IN(R0|R1|R2)|OUT(R1|R2),r[0],r[1],r[2],&r[1],&r[2]);
  422.     break;
  423.   
  424.    case OS_EnterOS: 
  425. #ifdef DEBUG
  426.     Normal(w);
  427.     printf("***OS_EnterOS (ignored) from %08x ****\n",r[15]);
  428.     Virtual(w);
  429. #endif
  430.     if (w->ingos) {
  431.        r[15] = r[15] | 0x03;
  432.     }
  433.     break;
  434.   
  435.    case OS_IntOff: 
  436. #ifdef DEBUG
  437.     Normal(w);
  438.     printf("***OS_IntOff (ignored) from %08x ****\n",r[15]);
  439.     Virtual(w);
  440. #endif
  441.     break;
  442.   
  443.    case OS_IntOn: 
  444. #ifdef DEBUG
  445.     Normal(w);
  446.     printf("***OS_IntOn (ignored) from %08x ****\n",r[15]);
  447.     Virtual(w);
  448. #endif
  449.     break;
  450.   
  451.    case OS_Exit: 
  452. #ifdef DEBUG
  453.     Normal(w);
  454.     printf("***OS_Exit from %08x ****\n",r[15]);
  455.     Virtual(w);
  456. #endif
  457.     if (-1==w->Exit)
  458.     {
  459.       if (w->started_ingos) {
  460.         usermode();
  461.         strcpy(w->command, "gos");
  462.         swi(OS_CLI,IN(R0),w->command);
  463.       }
  464.       else {
  465.         Normal(w);
  466.         printflush(w);
  467.         RealDoOff(w);
  468.       }
  469.     }
  470.  
  471. /*
  472.  *  The return value Sys$ReturnCode has to be set here
  473.  *  Normally OS_Exit does this, but is never called here.
  474.  */
  475.     if (r[1] == 0x58454241) { /* ABEX */
  476.        int val = r[2];
  477.        Normal(w);
  478.        err = swix(OS_SetVarVal, IN(R0|R1|R2|R3|R4),"Sys$ReturnCode", &val, 4, 0, 1);
  479.        Virtual(w);
  480.     }
  481.     r[15] = w->Exit;
  482.     r[12] = w->ExitR12;
  483.     break;
  484.   
  485.    case OS_GenerateError: 
  486.     { char buf[264];
  487.       Normal(w);
  488.       FromMem(w,r[0],buf,sizeof(buf));
  489.       printf("***GenerateError: PC=%08x %d %s\n",r[15],((int *)buf)[0],buf+4);
  490.       Virtual(w);
  491.     }
  492.     getc(w);
  493.     err = (void *)r[0];
  494.     break;
  495.   
  496.    case OS_ChangeEnvironment: 
  497.     switch (r[0])
  498.     { int t;
  499.   #define ifswap(x,y) ((x)?((t)=(x),(x)=(y),(y)=(t)):((x)=(y)))
  500.       default: goto uk;
  501.       case 0: ifswap(r[1],w->MemoryLimit); break;
  502.       case 1: ifswap(r[1],w->UndefinedInstruction); break;
  503.       case 2: ifswap(r[1],w->PrefetchAbort); break;
  504.       case 3: ifswap(r[1],w->DataAbort); break;
  505.       case 4: ifswap(r[1],w->AddressException); break;
  506.       case 5: ifswap(r[1],w->OtherExceptions); break;
  507.       case 6: ifswap(r[1],w->Error); ifswap(r[2],w->ErrorR0); ifswap(r[3],w->ErrorBuf); break;
  508.       case 7: ifswap(r[1],w->CallBack); ifswap(r[2],w->CallBackR12); ifswap(r[3],w->CallBackBuf); break;
  509.       case 8: ifswap(r[1],w->BreakPoint); ifswap(r[2],w->BreakPointR12); ifswap(r[3],w->BreakPointBuf); break;
  510.       case 9: ifswap(r[1],w->Escape); ifswap(r[2],w->EscapeR12); break;
  511.       case 10: ifswap(r[1],w->Event); ifswap(r[2],w->EventR12); break;
  512.       case 11: ifswap(r[1],w->Exit); ifswap(r[2],w->ExitR12); break;
  513.       case 12: ifswap(r[1],w->UnusedSWI); ifswap(r[2],w->UnusedSWIR12); break;
  514.       case 13: ifswap(r[1],w->ExceptionRegs); break;
  515.       case 14: ifswap(r[1],w->ApplicationSpace); break;
  516.       case 15: ifswap(r[1],w->CurrentlyActiveObject); break;
  517.       case 16: ifswap(r[1],w->UpCall); ifswap(r[2],w->UpCallR12); break;
  518.     }
  519.     break;
  520.   
  521.    case OS_SetEnv: 
  522.     { int t;
  523.       ifswap(r[0],w->Exit);
  524.       ifswap(r[1],w->MemoryLimit);
  525.       ifswap(r[2],w->ApplicationSpace);
  526.       ifswap(r[4],w->UndefinedInstruction);
  527.       ifswap(r[5],w->PrefetchAbort);
  528.       ifswap(r[6],w->DataAbort);
  529.       ifswap(r[7],w->AddressException);
  530.     }
  531.     break;
  532.  
  533.    case OS_Control: {
  534.       int t;
  535.       ifswap(r[0],w->Error); ifswap(r[1],w->ErrorBuf);
  536.       ifswap(r[2],w->Escape);
  537.       ifswap(r[3],w->Event);
  538.     }
  539.     break;
  540.  
  541.    case OS_ReadVduVariables: {
  542.       int i = 0, value;
  543.       Normal(w);
  544.       while (FromMem(w, r[0] + i, &value, 4), value != -1) i += 4;
  545.       Virtual(w);
  546.       ReadRange(w, r[0], r[0] + i);
  547.       WriteRange(w, r[1], r[1] + i);
  548.       err = swix(OS_ReadVduVariables, IN(R0|R1), r[0], r[1]);
  549.     }
  550.     break;
  551.  
  552.    case OS_GetEnv: 
  553.     r[0]=(int)&w->command[0];
  554.     r[1]=w->MemoryLimit;
  555.     r[2]=(int)&w->starttime[0];
  556.     break;
  557.   
  558.    case OS_ReadVarVal: 
  559.     ReadRange(w,r[0],r[0]+256);
  560.     if (r[2]>=0)
  561.       WriteRange(w,r[1],r[1]+r[2]);
  562.     err = swix(OS_ReadVarVal,IN(R0|R1|R2|R3|R4)|OUT(R2|R3|R4),r[0],r[1],r[2],r[3],r[4],&r[2],&r[3],&r[4]);
  563.     break;
  564.  
  565.    case OS_SetVarVal:
  566.     ReadRange(w, r[0], r[0] + 256);
  567.     if (r[2] > 0)
  568.       ReadRange(w, r[1], r[1] + r[2]);
  569.     if (r[3] > 0)
  570.       ReadRange(w, r[3], r[3] + 256);
  571.     err = swix(OS_SetVarVal,IN(R0|R1|R2|R3|R4)|OUT(R3|R4),r[0],r[1],r[2],r[3],r[4],&r[3],&r[4]);
  572.     break;
  573.   
  574.    case OS_Module: 
  575.     switch (r[0])
  576.     { default: goto uk;
  577.       case 6:
  578.         Normal(w);
  579.         err = swix(OS_Module,IN(R0|R3)|OUT(R2),r[0],r[3],&r[2]);
  580.         Virtual(w);
  581.         break;
  582.       case 7:
  583.         Normal(w);
  584.         err = swix(OS_Module,IN(R0|R2),r[0],r[2]);
  585.         Virtual(w);
  586.         break;
  587.       case 18:
  588.         ReadRange(w,r[1],r[1]+256);
  589.         err = swix(OS_Module,IN(R0|R1)|OUT(R1|R2|R3|R4|R5),
  590.                         r[0],r[1],&r[1],&r[2],&r[3],&r[4],&r[5]);
  591.         break;
  592.     }
  593.     break;
  594.  
  595.    case OS_ConvertHex8:
  596.     WriteRange(w,r[1],r[1]+r[2]);
  597.     err = swix(OS_ConvertHex8,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
  598.     break;
  599.  
  600.    case OS_CLI: 
  601.     { char buf[256];
  602.       Normal(w);
  603.       FromMem(w,r[0],buf,sizeof(buf));
  604.       if ((buf[0]|0x20)=='g' && (buf[1]|0x20)=='o' && (buf[2]|0x20)=='s' && buf[3]<=' ')
  605.          w->ingos = 1;
  606. /*
  607.  * Before loading a new programme into memory the old and new pages
  608.  * should be on the same addresses.
  609.  */
  610.       FixMemoryPages(w);
  611.       {
  612.         int i = 0;
  613.         while ((w->command[i] = buf[i]) >= ' ') i++;
  614.         w->command[i] = 0;
  615.       }
  616.       err=swix(OS_CLI,IN(R0),buf);
  617.       Virtual(w);
  618.     }
  619.     break;
  620.  
  621.    case OS_Mouse:  
  622.      Normal(w);
  623.      err = swix(OS_Mouse,OUT(R0|R1|R2|R3),&r[0],&r[1],&r[2],&r[3]);
  624.      Virtual(w);
  625.      break;
  626.  
  627.    case OS_ReadMonotonicTime:  
  628.      Normal(w);
  629.      err = swix(OS_ReadMonotonicTime,OUT(R0),&r[0]);
  630.      Virtual(w);
  631.      break;
  632.  
  633.    case OS_SWINumberFromString: 
  634.     { char buf[256];
  635.       Normal(w);
  636.       FromMem(w,r[1],buf,sizeof(buf));
  637.       err=swix(OS_SWINumberFromString,IN(R1)|OUT(R0),&buf,&r[0]);
  638.       Virtual(w);
  639.     }
  640.     break;
  641.  
  642.    /* Filesystem SWIs */
  643.    case OS_Find: 
  644.     if (!r[0])
  645.     { Normal(w);
  646.       err = swix(OS_Find,IN(R0|R1)|OUT(PSW),r[0],r[1],&psw);
  647.       Virtual(w);
  648.     }
  649.     else
  650.     { char name[256];
  651.       char path[256];
  652.       Normal(w);
  653.       FromMem(w,r[1],name,sizeof(name));
  654.       if ((r[0]&3)==1 || (r[0]&3)==2)
  655.         FromMem(w,r[2],path,sizeof(path));
  656.       err = swix(OS_Find,IN(R0|R1|R2)|OUT(PSW|R0),r[0],name,path,&psw,&r[0]);
  657.       Virtual(w);
  658.     }
  659.     break;
  660.   
  661.    case OS_BGet: case OS_BPut: case OS_Args: 
  662.     Normal(w);
  663.     err=swix(swinum,IN(R0|R1|R2)|OUT(PSW|R0|R1|R2),r[0],r[1],r[2],&psw,&r[0],&r[1],&r[2]);
  664.     r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  665.     Virtual(w);
  666.     break;
  667.   
  668.    case OS_GBPB: 
  669.     Normal(w);
  670.     if (1<=r[0] && r[0]<=4)
  671.     { /* read/write variety */
  672.       while (r[3]>0)
  673.       { RANGE k = Physical(w,r[2],r[2]+r[3]);
  674.         int p = k.start;
  675.         int l = k.end-k.start;
  676.         int q,m;
  677.         err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),r[0],r[1],p,l,r[4],&psw,&q,&m,&r[4]);
  678.         r[2]+=q-p;
  679.         r[3]-=l-m;
  680.         if (err || m)
  681.           break;
  682.     } }
  683.     else if (5<=r[0] && r[0]<=8)
  684.     { char buf[2048];
  685.       FromMem(w,r[2],buf,sizeof(buf));
  686.       err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R3|R4),r[0],buf,r[2],r[3],r[4],&psw,&r[3],&r[4]);
  687.       ToMem(w,buf,r[2],sizeof(buf));
  688.     }
  689.     else if (9<=r[0] && r[0]<=12)
  690.     { char dirname[256];
  691.       char wild[256];
  692.       RANGE k;
  693.       FromMem(w,r[1],&dirname,sizeof(dirname));
  694.       if (r[6])
  695.         FromMem(w,r[6],&wild,sizeof(wild));
  696.       k = Physical(w,r[2],r[2]+r[5]);
  697.       err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(PSW|R3|R4),
  698.         r[0],dirname,k.start,r[3],r[4],k.end-k.start,r[6]?wild:0,
  699.         &psw,&r[3],&r[4]);
  700.     }
  701.     else
  702.     { Virtual(w);
  703.       goto uk;
  704.     }
  705.     r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  706.     Virtual(w);
  707.     break;
  708.   
  709.    case OS_File: 
  710.     Normal(w);
  711.     switch(r[0])
  712.     { default: Virtual(w); goto uk;
  713.       case 0: case 10:                          /* save a block of memory */
  714.       {
  715.         char name[256];
  716.         int s[16];
  717.         int h;
  718.         FromMem(w,r[1],name,sizeof(name));
  719.         err = swix(OS_Find,IN(R0|R1)|OUT(R0),0x8F,name,&h);
  720.         if (err) break;
  721.         /* write code from OS_GBPB handler above */
  722.         s[0]=2; s[1]=h; s[2]=r[4]; s[3]=r[5]-r[4];
  723.         while (s[3]>0)
  724.         { RANGE k = Physical(w,s[2],s[2]+s[3]);
  725.           int p = k.start;
  726.           int l = k.end-k.start;
  727.           int q,m;
  728.           err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),s[0],s[1],p,l,s[4],&psw,&q,&m,&s[4]);
  729.           s[2]+=q-p;
  730.           s[3]-=l-m;
  731.           if (err || m)
  732.             break;
  733.         } 
  734.         err = swix(OS_Find,IN(R0|R1),0,h);
  735.         if (err) break;
  736.         if (r[0] == 0)
  737.         {
  738.           err = swix(OS_File,IN(R0|R1|R2),2,name,r[2]);
  739.           if (err) break;
  740.           err = swix(OS_File,IN(R0|R1|R3),3,name,r[3]);
  741.         } else
  742.         {
  743.           err = swix(OS_File,IN(R0|R1|R2),18,name,r[2]);
  744.         }
  745.         break;
  746.       }
  747.       case 5: case 13: case 15: case 17:        /* read cat info */
  748.       case 20: case 21: case 22: case 23:
  749.       { int h;
  750.         char path[256];
  751.         char name[256];
  752.         FromMem(w,r[1],name,sizeof(name));
  753.         if (r[0]==13 || r[0]==15 || r[0]==21 || r[0]==22)
  754.           FromMem(w,r[4],path,sizeof(path));
  755.         err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5|R6),r[0],name,path,
  756.                                         &r[0],&r[2],&r[3],&r[4],&r[5],&h);
  757.         if (20<=r[0] && r[0]<=23)
  758.           r[6]=h;
  759.         break;
  760.       }
  761.       case 1: case 2: case 3: case 4: case 9: case 18:  /* Write cat info */
  762.       case 6:           /* Delete */
  763.       case 7: case 11:  /* Create */
  764.       case 8:           /* Create directory */
  765.       { char name[256];
  766.         FromMem(w,r[1],name,sizeof(name));
  767.         err = swix(OS_File,IN(R0|R1|R2|R3|R4|R5)|OUT(R0|R2|R3|R4|R5),r[0],name,r[2],r[3],r[4],r[5],
  768.                                         &r[0],&r[2],&r[3],&r[4],&r[5]);
  769.         break;
  770.       }
  771.       case 12: case 14: case 16: case 255:      /* load */
  772.       { int h;
  773.         char path[256];
  774.         char name[256];
  775.         RANGE k;
  776.         int l,m,q;
  777.         int p=(r[3]&0xFF)?-1:r[2];
  778.         int t = r[0]==255?0:r[0]==12?1:r[0]==14?2:r[0]==16?3:0;
  779.         FromMem(w,r[1],name,sizeof(name));
  780.         if (t==1 || t==2)
  781.           FromMem(w,r[4],path,sizeof(path));
  782.         err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5),"\x05\x0D\x0F\x11"[t],name,path,
  783.                                         &r[0],&r[2],&r[3],&r[4],&r[5]);
  784.         if (err)
  785.           break;
  786.         err = swix(OS_Find,IN(R0|R1|R2)|OUT(R0),0x4C+t,name,path,&h);
  787.         if (err)
  788.           break;
  789.         if (p==-1)
  790.           p = r[2];
  791.         l = r[4];
  792.         while (l>0)
  793.         { k = Physical(w,p,p+l);
  794.           if (!k.start)
  795.           { err=ERR(&BadMemory);
  796.             break;
  797.           }
  798.           err = swix(OS_GBPB,IN(R0|R1|R2|R3)|OUT(R2|R3),4,h,k.start,k.end-k.start,&q,&m);
  799.           if (err)
  800.             break;
  801.           if (q!=k.end || m)
  802.           { err = ERR(&Failed);
  803.             break;
  804.           }
  805.           p+=k.end-k.start;
  806.           l-=k.end-k.start;
  807.         }
  808.         if (!err)
  809.           err = swix(OS_Find,IN(R0|R1),0,h);
  810.         else
  811.           (void)swix(OS_Find,IN(R0|R1),0,h);
  812.       }
  813.     }
  814.     Virtual(w);
  815.     break;
  816.   
  817.    case OS_FSControl: 
  818.     Normal(w);
  819.     switch (r[0])
  820.     { default: Virtual(w); goto uk;
  821.       case 27:          /* Wipe objects */
  822.       { char name[256];
  823.         FromMem(w,r[1],name,sizeof(name));
  824.         err = swix(OS_FSControl,IN(R0|R1|R2|R3|R4|R5|R6|R7),r[0],name,r[2],r[3],r[4],r[5],r[6],r[7]);
  825.         break;
  826.       }
  827.     }
  828.     Virtual(w);
  829.     break;
  830.   
  831.     /*
  832.      * RISCOS extension module SWIs
  833.      */
  834.      
  835. #ifndef SharedCLibrary_LibInitAPCS_R
  836. #define SharedCLibrary_LibInitAPCS_R 0x80681
  837. #endif
  838.    case SharedCLibrary_LibInitAPCS_R: 
  839.     ReadRange(w,r[0],r[0]+256);
  840.     WriteRange(w,r[1],r[1]+32768);
  841.     err = swix(SharedCLibrary_LibInitAPCS_R,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(R0|R1|R2|R6),
  842.         r[0],r[1],r[2],r[3],r[4],r[5],r[6],&r[0],&r[1],&r[2],&r[6]);
  843.     break;
  844.   
  845.    case DDEUtils_Prefix: 
  846.     Normal(w);
  847.     if (r[0] > 0) ReadRange(w,r[0],r[0]+256);
  848.     err = swix(DDEUtils_Prefix, IN(R0), r[0]);
  849.     Virtual(w);
  850.     break;
  851.  
  852.    case DDEUtils_SetCLSize: 
  853.     Normal(w);
  854.     free(w->DDECL);
  855.     w->DDECLSize = r[0];
  856.     w->DDECL = alloc(r[0]);
  857.     Virtual(w);
  858.     break;
  859.   
  860.    case DDEUtils_SetCL: 
  861.     Normal(w);
  862.     FromMem(w,r[0],w->DDECL,w->DDECLSize);
  863.     Virtual(w);
  864.     break;
  865.   
  866.    case DDEUtils_GetCLSize: 
  867.     r[0] = w->DDECLSize;
  868.     break;
  869.   
  870.    case DDEUtils_GetCL: 
  871.     Normal(w);
  872.     ToMem(w,w->DDECL,r[0],w->DDECLSize);
  873.     w->DDECLSize = 0; 
  874.     Virtual(w);
  875.     break;
  876.   
  877.    case DDEUtils_ThrowbackStart: 
  878.     Normal(w);
  879.     err = swix(DDEUtils_ThrowbackStart,0);
  880.     Virtual(w);
  881.     break;
  882.   
  883.    case DDEUtils_ThrowbackSend: 
  884.     { char file[256];
  885.       char msg[256];
  886.       Normal(w);
  887.       FromMem(w,r[2],&file,sizeof(file));
  888.       if (r[0])
  889.         FromMem(w,r[5],&msg,sizeof(msg));
  890.       err = swix(DDEUtils_ThrowbackSend,IN(R0|R2|R3|R4|R5),r[0],file,r[3],r[4],msg);
  891.       Virtual(w);
  892.       break;
  893.     }
  894.   
  895.    case DDEUtils_ThrowbackEnd: 
  896.     Normal(w);
  897.     err = swix(DDEUtils_ThrowbackEnd,0);
  898.     Virtual(w);
  899.     break;
  900.   
  901.    case MessageTrans_Lookup:
  902.    case MessageTrans_ErrorLookup:
  903.     ReadRange(w,r[1],r[1]+256);
  904.     if (r[2])
  905.       WriteRange(w,r[2],r[2]+r[3]);
  906.     err = swix(swinum,IN(R0|R1|R2|R3|R4|R5|R6|R7)|OUT(R0|R2|R3),
  907.         r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],&r[0],&r[2],&r[3]);
  908.     break;
  909.   
  910.    case Wimp_ReadSysInfo: 
  911.     err = swix(Wimp_ReadSysInfo,IN(R0)|OUT(R0),r[0],&r[0]);
  912.     break;
  913.  
  914.    case Wimp_SendMessage: 
  915.     ReadRange(w,r[1],r[1]+256);
  916.     err = swix(Wimp_SendMessage,IN(R0|R1|R2)|OUT(R2),r[0],r[1],r[2],&r[2]);
  917.     break;
  918.   
  919.    case FPEmulator_Version: 
  920.     err = swix(FPEmulator_Version,OUT(R0),&r[0]);
  921.     break;
  922.   
  923.    case Territory_ReadCurrentTimeZone: 
  924.     err = swix(Territory_ReadCurrentTimeZone,OUT(R0|R1),&r[0],&r[1]);
  925.     break;
  926.   
  927.    case Territory_ReadTimeZones: 
  928.     err = swix(Territory_ReadTimeZones,IN(R0)|OUT(R0|R1|R2|R3),r[0],&r[0],&r[1],&r[2],&r[3]);
  929.     break;
  930.   
  931.    case Territory_ConvertTimeToOrdinals: 
  932.     ReadRange(w,r[1],r[1]+5);
  933.     WriteRange(w,r[2],r[2]+32);
  934.     err = swix(Territory_ConvertTimeToOrdinals,IN(R0|R1|R2),r[0],r[1],r[2]);
  935.     break;
  936.  
  937.    case Wimp_SlotSize: 
  938. /*
  939.  * When this SWI is allowed, the wimpslot will be expanded to the
  940.  * maximum value, or sometimes to a wrong value.
  941.  * In the first case there is no space left for Edit's taskwindow,
  942.  * so Virtual will stop. 
  943.  * I think a programme running under Virtual must not change its
  944.  * 'Wimp_Slot'. The user can make any changes to the WimpSlot by
  945.  * dragging a bar in the Tasks window.
  946.  *
  947.  * When a task wants to enlarge the wimpslot, ie make the 'DiskSlot'
  948.  * bigger, will this be allowed.
  949.  *
  950.  * So this code is not compiled
  951.  *
  952.     swi(Wimp_SlotSize,IN(R0|R1),OUT(R1|R2),-1,r[1],&r[1],&r[2]);
  953.     if (r[0]!=-1)
  954.     { w->ApplicationSpace = r[0];
  955.       w->MemoryLimit = r[0];
  956.     }
  957.     r[0]=w->ApplicationSpace;
  958.     break;
  959.  *
  960.  * So here's my new code
  961.  */
  962.     if (r[0] != -1) {
  963.       if (r[0] > w->ApplicationSpace - K32) {           /* task asks for wimpslot extension */
  964.         int i, OldAppSpace = w->ApplicationSpace;
  965.         w->ApplicationSpace = ADDR(PLACE(r[0] + K32 + K32));
  966.         if (w->ApplicationSpace > M24)
  967.           w->ApplicationSpace = M24;
  968.         w->MemoryLimit = w->ApplicationSpace;
  969.         for (i = PLACE(OldAppSpace); i < PLACE(w->ApplicationSpace); i++) {
  970.           w->ourmem[i] = TAGLOC(ZERO, 0);
  971.         }
  972.       }
  973.     }
  974.     r[0] = w->ApplicationSpace - K32;
  975.     break;
  976.   
  977.   /* BASICTrans swis */
  978.   case BASICTrans_HELP:
  979.   case BASICTrans_Message:
  980.   case BASICTrans_Error:
  981.     V2Ext(w);
  982.     err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
  983.                            OUT(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
  984.          r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
  985.         &r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
  986.     Ext2V(w);
  987.     break;
  988.  
  989.   case TaskWindow_TaskInfo:  
  990.      Normal(w);
  991.      if (r[0] == 0)
  992.        r[0] = 1;
  993.      else
  994.        err = swix(TaskWindow_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
  995.      Virtual(w);
  996.      break;
  997.  
  998.   case Virtual_TaskInfo:  
  999.      Normal(w);
  1000.      if (r[0] == 0)
  1001.        r[0] = 1;
  1002.      else
  1003.        err = swix(Virtual_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
  1004.      Virtual(w);
  1005.      break;
  1006.  
  1007.   case VM_TaskInfo:
  1008.      err = ERR(&NotAllowed);
  1009.      break;
  1010.  
  1011.    /*
  1012.     * Default (unrecognized SWIs) handling
  1013.     */
  1014.   
  1015.    default: 
  1016.     if (swinum>=0x100 && swinum<0x200)
  1017.     { outc(w,(char)swinum);
  1018.       break;
  1019.     }
  1020.  
  1021.   uk:
  1022.     Normal(w);
  1023.     swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
  1024.     printf("UKSwi %s PC=%08x ",s,r[15]);
  1025.     for (i=0;i<=8;i++)
  1026.       printf("R%d=%08x ",i,r[i]);
  1027.     printf("Allow(Yn)?\n");
  1028.     Virtual(w);
  1029.   lp:
  1030.     switch (getc(w))
  1031.     { case -1:
  1032.         w->EscapeCondition = 0;
  1033.         /* FALL THROUGH */
  1034.       default:
  1035.         goto lp;
  1036.       case 'n': case'N':
  1037.         err = ERR(&NotAllowed);
  1038.         break;
  1039.       case 'y': case 'Y': case 13:
  1040.         V2Ext(w);
  1041.         err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
  1042.                                OUT(PSW|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
  1043.              r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
  1044.        &psw,&r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
  1045.         r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  1046.         Ext2V(w);
  1047.         break;
  1048.     }
  1049.     break;
  1050.   
  1051.   }
  1052.   if (!err)
  1053.     return w;
  1054.   if (instr&XOS_Bit) /* X form */
  1055.   { r[0]=(int)err;
  1056.     r[15]|=V_bit;
  1057.     return w;
  1058.   }
  1059.   if (-1==w->Error)
  1060.   { Normal(w);
  1061.     printf("***Error:%s",err->msg);
  1062.     RealDoOff(w);
  1063.   }
  1064.   WriteRange(w,w->ErrorBuf,w->ErrorBuf+264);
  1065.   ((int*)w->ErrorBuf)[0] = r[15];
  1066.   ((int*)w->ErrorBuf)[1] = err->num;
  1067.   strcpy( (char *)&((int*)w->ErrorBuf)[2], err->msg );
  1068.   r[0] = w->ErrorR0;
  1069.   r[15] = w->Error & ~3;
  1070.   return w;
  1071. }
  1072.  
  1073.  int CVUpCall( int r0, int r1, int r2, WKSP *w) 
  1074. { /* Called with sp a 1K chunk out of svcstack */
  1075.   switch(r0)
  1076.   { case 256:
  1077.       r0 = 0; /* Not quite sure what on earth is going on here, but better stop it! */
  1078.       break;
  1079.     default:
  1080.       break;
  1081.   }
  1082.     return r0;
  1083. }
  1084.  
  1085.  
  1086. /* ******************** Ext mode handlers */
  1087.  int CExtWriteC(int c, WKSP *w) 
  1088. { /* called with stack a 1K bit out of svcstack */
  1089.   w->outbuf[w->outcount++]=c;
  1090.   if (w->outcount>=OUTMAX-2)
  1091.   { Ext2Norm(w);
  1092.     printflush(w);
  1093.     FindPages(w);
  1094.     Norm2Ext(w);
  1095.   }
  1096.   return 0x80000000;     /* VC CC */
  1097. }
  1098.  
  1099.  int CExtUpCall(int r0,int r1,int r2,WKSP *w) 
  1100. { /* Called with sp a 1K chunk out of svcstack */
  1101.   switch(r0)
  1102.   { case 256:
  1103.       r0 = 0;
  1104.       break;
  1105.     default:
  1106.       break;
  1107.   }
  1108.   return r0;
  1109. }
  1110.  
  1111.  int CExtError(WKSP *w) 
  1112. { /* Called in user, ext mode */
  1113.   printf("ExtError PC=%08x errnum %d errmess %s****\n",w->errPC,w->errnum,w->errmess);
  1114.   Ext2V(w);
  1115.   return (int)&w->errnum;
  1116. }
  1117.  
  1118.  void CExtExit(WKSP *w) 
  1119. { /* Called in user, ext mode */
  1120.   Ext2V(w);
  1121. }
  1122.  
  1123.  
  1124. /* ******************** Normal mode handlers */
  1125.  void __main(private *p,char *cmd) 
  1126. { /* This is called in user mode, with its stack at the top of the WimpSlot */
  1127.   wimp_eventdata b;
  1128.   struct Error *e;
  1129.   char *buf[512];
  1130.   int ourtask,outtask,txt,i;
  1131.   WKSP *w;
  1132.  
  1133. #ifdef DEBUG 
  1134.   printf("%s\n", cmd);
  1135. #endif
  1136.  
  1137.   swi(OS_ReadArgs,IN(R0|R1|R2|R3),
  1138.    ",wimpslot/K,name/K,pagefile/K,ctrl/S,display/S,quit/S,task,txt,discslot/K,nice/K", cmd, buf, sizeof(buf));
  1139.  
  1140. #ifdef DEBUG 
  1141.   printf("os_readargs passed\n");
  1142. #endif
  1143.  
  1144.   if (buf[0] == 0) {
  1145.     strcpy(b.msg.data.chars+8, "gos ");
  1146.     strcpy(b.msg.data.chars+12, cmd);
  1147.   }
  1148.   else
  1149.     strcpy(b.msg.data.chars+8,cmd);
  1150.  
  1151.   swi(Wimp_Initialise,IN(R0|R1|R2)|OUT(R0|R1),200,0x4b534154,
  1152.                 buf[2]?buf[2]:"Virtual",&wimp_version,&ourtask);
  1153.   if (!buf[7] || !buf[8])
  1154.   { memcpy(b.msg.data.chars,"virtual ",8);
  1155.     b.msg.hdr.action = 0x808c5; /* TaskWindow_NewTask; */
  1156.     b.msg.hdr.your_ref = 0;
  1157.     b.msg.hdr.size = (21+(strlen(b.msg.data.chars)|3));
  1158.     swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,0);
  1159.     swi(OS_Exit,0);
  1160.   }
  1161.   outtask = xtoi(buf[7]);
  1162.   txt = xtoi(buf[8]);
  1163.  
  1164.   b.msg.hdr.action = /*TaskWindow_Ego*/ 0x808c2;
  1165.   b.msg.hdr.your_ref = 0;
  1166.   b.msg.data.words[0]=txt;
  1167.   b.msg.hdr.size = 24;
  1168.   swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,outtask);
  1169.  
  1170.   w = alloc(sizeof(WKSP));
  1171.   p->w = w;
  1172.   p->uses++;
  1173.   w->private = p;
  1174.   w->outtask = outtask;
  1175.   w->ourtask = ourtask;
  1176.   w->outcount = 0;
  1177.   w->incount = 0;
  1178.   w->instart = 0;
  1179.   w->EscapeCondition = 0;
  1180.   w->EscapeChar = 27;
  1181.   w->EscapeCharEnable = 0;
  1182.   w->ingos = 0;
  1183.   w->started_ingos = 0;
  1184.   w->moreavailable = 0;
  1185.  
  1186.   /* check for DDE extended command line */
  1187.   e = swix(DDEUtils_GetCLSize, OUT(R0), &i);
  1188.   if ((!e) && (i != 0))
  1189.   {
  1190.     w->DDECL = alloc(i);
  1191.     w->DDECLSize = i;
  1192.     swix(DDEUtils_GetCL, IN(R0), w->DDECL);
  1193.   } else
  1194.   {
  1195.     w->DDECL = 0;
  1196.     w->DDECLSize = 0;
  1197.   }
  1198.  
  1199.   if (buf[10] == 0)
  1200.   {                      
  1201.     w->nice_run = 15;    /* default */
  1202.     w->nice_delay = 0;
  1203.   } else
  1204.   {
  1205.     int level =sizetoi(buf[10]);
  1206.     w->nice_delay = 0;
  1207.     switch (level)
  1208.     {
  1209.       case 0: w->nice_run = 100;break;
  1210.       case 1: w->nice_run = 75; break;
  1211.       case 2: w->nice_run = 45; break;
  1212.       case 3: w->nice_run = 25; break;
  1213.       case 4: w->nice_run = 15; break;
  1214.       case 5: w->nice_run = 13;
  1215.               w->nice_delay = 10;
  1216.               break;
  1217.       case 6: w->nice_run = 11;
  1218.               w->nice_delay = 25;
  1219.               break;
  1220.       case 7: w->nice_run = 8;
  1221.               w->nice_delay = 50;
  1222.               break;
  1223.       case 8: w->nice_run = 7;
  1224.               w->nice_delay = 80;
  1225.               break;
  1226.       case 9: w->nice_run = 5;
  1227.               w->nice_delay = 100;
  1228.               break;
  1229.       default: w->nice_run = 100; break;
  1230.     }
  1231.   }
  1232.  
  1233.   e = swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,p);
  1234.   e = swix(OS_CallEvery,IN(R0|R1|R2),w->nice_run,&OurCallEvery,p);
  1235.  
  1236.   strcpy(w->pagefilename,buf[3]?buf[3]:"<Swap$Path>pagefile0");
  1237.   strcpy(w->command,buf[0]?buf[0]:"GOS");
  1238.  
  1239.   w->ApplicationSpace=buf[9]?sizetoi(buf[9])+K32:M24;
  1240.   if (w->ApplicationSpace>M24)
  1241.     w->ApplicationSpace=M24;
  1242.  
  1243.   if (buf[1] != 0)
  1244.   {
  1245.     int slotsize = sizetoi(buf[1]);
  1246.     if (slotsize<K32) slotsize = K32;
  1247.     swi(Wimp_SlotSize, IN(R0|R1), slotsize, -1);
  1248.   }
  1249.  
  1250.   w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
  1251.   i=0;
  1252.   while (0!=(e=swix(OS_Find,IN(R0|R1)|OUT(R0),0x80,w->pagefilename,&w->pagefile)) && i<10)
  1253.     w->pagefilename[strlen(w->pagefilename)-1]++,i++;
  1254.   if (e)
  1255.   { swi(Wimp_ReportError,IN(R0|R1|R2),e,2,"Virtual");
  1256.     swi(OS_Exit,0);
  1257.   }
  1258.   svcmode();
  1259.   swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
  1260. #ifdef DEBUG
  1261.   printf("cmd=%s\n",w->command);
  1262.   printf("wimpslot=%08x\n",w->ApplicationSpace);
  1263.   printf("name=%s\n",buf[2]);
  1264.   printf("pagefile=%s\n",w->pagefilename);
  1265.   printf("ctrl=%08x\n",(int)buf[4]);
  1266.   printf("display=%08x\n",(int)buf[5]);
  1267.   printf("quit=%08x\n",(int)buf[6]);
  1268.   printf("task=%08x\n",outtask);
  1269.   printf("txt=%08x\n",txt);
  1270.   printf("nice=%d\n",w->nice_run);
  1271. #endif
  1272.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),6,&NormError,w,&w->errPC,
  1273.                         &w->OldError,&w->OldErrorR0,&w->OldErrorBuf);
  1274.   swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),16,&NormUpCall,w,&w->OldUpCall,&w->OldUpCallR12);
  1275.   swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),11,&NormExit,w,&w->OldExit,&w->OldExitR12);
  1276.  
  1277.   Initourmem(w);
  1278.   SetWimpMemMap(w);
  1279.   SetVirtualSlot(w,w->ApplicationSpace-K32);
  1280.   w->MemoryLimit = w->ApplicationSpace;
  1281. #ifdef DEBUG
  1282.   printf("Going virtual\n");
  1283. #endif
  1284.   Virtual(w);
  1285.   usermode();
  1286.   worksemaphore = 0;    /* Enable interupts */
  1287. #ifdef DEBUG
  1288.   swi(OS_Write0,IN(R0),"This is virtual: OS_CLI ");
  1289.   swi(OS_Write0,IN(R0),w->command);
  1290.   swi(OS_NewLine,0);
  1291. #endif
  1292.  
  1293.   if ((w->command[0]|0x20)=='g' && (w->command[1]|0x20)=='o' && (w->command[2]|0x20)=='s' && w->command[3]<=' ')
  1294.     w->started_ingos = 1;
  1295.   else
  1296.     w->started_ingos = 0;
  1297.  
  1298.   if (buf[6] == 0) w->started_ingos = 1;
  1299.  
  1300.   swi(OS_CLI,IN(R0),w->command);
  1301.   swi(OS_Exit,0);
  1302. }
  1303.  
  1304.  void RealDoOff(WKSP *w) 
  1305. {
  1306.   private *priv=w->private;
  1307.   wimp_eventdata b;
  1308. #ifdef DEBUG
  1309.   printf("RealDoOff\n");
  1310. #endif
  1311.   swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
  1312.   printflush(w);
  1313.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),6,w->OldError,w->OldErrorR0,w->OldErrorBuf);
  1314.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,w->OldExit,w->OldExitR12);
  1315.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,w->OldUpCall,w->OldUpCallR12);
  1316.   Finishourmem(w);
  1317.   usermode();
  1318.   b.msg.hdr.action = /*TaskWindow_Morio*/ 0x808c3;
  1319.   b.msg.hdr.your_ref = 0;
  1320.   b.msg.hdr.size = 20;
  1321.   swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,w->outtask);
  1322.   swi(Wimp_CloseDown, 0);
  1323.   swix(OS_Find,IN(R0|R1),0,w->pagefile);
  1324.   swix(OS_File,IN(R0|R1),6,w->pagefilename);
  1325.   free((char *)w->stacktop-STACKSIZE);
  1326.   free(w->DDECL);
  1327.   free(w);
  1328.   priv->uses--;
  1329.   priv->w = 0;
  1330.   swi(OS_Exit,0);
  1331. }
  1332.  
  1333.  int CNormError( WKSP *w )
  1334. { printf("NormError: PC=%08x errnum %d errmess %s\n",w->errPC,w->errnum,w->errmess);
  1335.   swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
  1336.   swi(Wimp_ReportError,IN(R0|R1|R2),&w->errnum,2,"Virtual");
  1337.   swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
  1338.   RealDoOff(w);
  1339.   return 0;
  1340. }
  1341.  
  1342.  void CNormExit(WKSP *w)
  1343. {
  1344. #ifdef DEBUG
  1345.   printf("NormExit\n");
  1346. #endif
  1347.   RealDoOff(w);
  1348. }
  1349.  
  1350.  int CNormWriteC(int c, WKSP *w) 
  1351. { /* called with stack a 1K bit out of svcstack */
  1352.   w->outbuf[w->outcount++]=c;
  1353.   if (w->outcount>=OUTMAX-2)
  1354.   { printflush(w);
  1355.     FindPages(w);
  1356.   }
  1357.   return 0x80000000;     /* VC CC */
  1358. }
  1359.  
  1360.  int CNormUpCall(int r0,int r1,int r2,WKSP *w) 
  1361. { /* Called with sp a 1K chunk out of svcstack */
  1362.   switch(r0)
  1363.   { case 256:
  1364.       { char *cmd, *tptr;
  1365.         Virtual(w);
  1366.         swi(OS_GetEnv,OUT(R0|R2),&cmd,&tptr);
  1367.         if ((w->command[0]|0x20)=='g' && (w->command[1]|0x20)=='o' && (w->command[2]|0x20)=='s' && w->command[3]<=' ')
  1368.            w->ingos = 1;
  1369.         else
  1370.            w->ingos = 0;
  1371.  
  1372. /*
  1373.  * Only execute this under RO3
  1374.  */
  1375.         if (wimp_version >= 300) strcpy(w->command,cmd);
  1376.  
  1377.         memcpy(w->starttime,tptr,5);
  1378.         worksemaphore = 0;    /* Enable interrupts */
  1379.         break;
  1380.       }
  1381.     default:
  1382.       break;
  1383.   }
  1384.   return r0;
  1385. }
  1386.